﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="EntitySession.cs" company="Data Ductus Malmö">
//   (c) 2010 - 2012 Data Ductus Malmö AB
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace DataDuctus.Snmp.Persistor.Core.Persistor
{
  using System;
  using System.Collections.Generic;
  using System.Linq;

  using DataDuctus.Snmp.Persistor.Core.MetaData;
  using DataDuctus.Snmp.Persistor.Core.Persistor.Internal;

  using Lextm.SharpSnmpLib;

  /// <summary>
  /// The entity session.
  /// </summary>
  public sealed class EntitySession : IDisposable
  {
    #region Fields

    /// <summary>
    /// The connection meta.
    /// </summary>
    private readonly IEnumerable<ConnectionMeta> connectionMeta;

    /// <summary>
    /// The factory.
    /// </summary>
    private readonly EntityPersistorFactory factory;

    #endregion

    #region Constructors and Destructors

    /// <summary>
    /// Initializes a new instance of the <see cref="EntitySession"/> class.
    /// </summary>
    /// <param name="factory">
    /// The factory.
    /// </param>
    /// <param name="connectionMeta">
    /// The connection meta.
    /// </param>
    public EntitySession(EntityPersistorFactory factory, IEnumerable<ConnectionMeta> connectionMeta)
    {
      this.connectionMeta = connectionMeta;
      this.factory = factory;
    }

    #endregion

    #region Public Methods and Operators

    /// <summary>
    /// The dispose.
    /// </summary>
    public void Dispose()
    {
    }

    /// <summary>
    /// The load.
    /// </summary>
    /// <typeparam name="T">
    /// </typeparam>
    /// <returns>
    /// The System.Collections.Generic.IEnumerable`1[T -&gt; T].
    /// </returns>
    public IEnumerable<T> Load<T>() where T : new()
    {
      ClassMeta clzMeta = this.factory.Config.Repository.Classes[typeof(T)];

      ConnectionMeta readConnection =
        (from conn in this.connectionMeta where conn.ConnectionType == ConnectionType.Read select conn).First();

      IList<Variable> result = new QueryExecutor(clzMeta).Execute(readConnection);

      return EntityHydrator.Hydrate<T>(result, clzMeta);
    }

    /// <summary>
    /// The save.
    /// </summary>
    /// <param name="obj">
    /// The obj.
    /// </param>
    /// <typeparam name="T">
    /// </typeparam>
    public void Save<T>(T obj)
    {
      ClassMeta clzMeta = this.factory.Config.Repository.Classes[typeof(T)];

      ConnectionMeta writeConnection =
        (from conn in this.connectionMeta where conn.ConnectionType == ConnectionType.Write select conn).First();

      EntityPersitor.Save(clzMeta, writeConnection, obj);
    }

    /// <summary>
    /// The save.
    /// </summary>
    /// <param name="objects">
    /// The objects.
    /// </param>
    /// <typeparam name="T">
    /// </typeparam>
    public void Save<T>(IEnumerable<T> objects)
    {
      ClassMeta clzMeta = this.factory.Config.Repository.Classes[typeof(T)];

      ConnectionMeta writeConnection =
        (from conn in this.connectionMeta where conn.ConnectionType == ConnectionType.Write select conn).First();

      EntityPersitor.Save(clzMeta, writeConnection, objects);
    }

    #endregion
  }
}